#!/bin/bash

#oos全局参数配置
host="oss-cn-shanghai.aliyuncs.com"
bucket="sh-qiaolian" # BucketName
accessKeyId="LTAI5t9j22p9i8Mwpwt2oFbs" # AccessKeyId
AccessKeySecret="iPnDbXKQDXyOfYAiiaE9WuBQSCD3Ot" # AccessKeySecret
osshost=$bucket.$host
topDirName= #桶的顶级目录名，不写的话直接检查桶的根目录

# 检查参数
if [ $# -eq 0 ]; then
    echo "错误：请提供要检查的文件或目录路径"
    echo "用法："
    echo "  $0 <源文件或目录> [目标OSS目录]"
    echo "示例："
    echo "  $0 test.txt images/"
    echo "  $0 images/ remote/images/"
    exit 1
fi
 
#第一个参数是文件或文件夹
sourceFileOrDir=$1
#第二个参数是需要检查的oss目录，相对于上面topDirName的目录下的
destDir=$2

# 检查源文件/目录是否存在
if [ ! -e "$sourceFileOrDir" ]; then
    echo "错误：源文件或目录 '$sourceFileOrDir' 不存在"
    exit 1
fi

# 输出文件
output_file="notexists.txt"
# 确保输出文件存在且为空
> "$output_file"
 
#检查的文件对象个数计数
checkedFilesCount=0
notExistFilesCount=0
 
#需要两个参数
#第一个入参：源文件，如a.txt
#第二个入参：检查oss的指定的目录下面
function checkFileInOss(){
    cur_source=$1
    cur_dest=$2
    echo "准备检查【${cur_source}】在 OSS【${cur_dest}】是否存在......."

    resource="/${bucket}/${topDirName}${cur_dest}"
    dateValue="$(TZ=GMT env LANG=en_US.UTF-8 date +'%a, %d %b %Y %H:%M:%S GMT')"
    check_stringToSign="HEAD\n\n\n${dateValue}\n${resource}"
    check_signature=$(echo -en "$check_stringToSign" | openssl sha1 -hmac "${AccessKeySecret}" -binary | base64)
    
    url="https://${osshost}/${topDirName}${cur_dest}"
    
    echo "检查文件是否存在: ${url}"
    check_response=$(curl -I -X HEAD \
        -H "Host: ${osshost}" \
        -H "Date: ${dateValue}" \
        -H "Authorization: OSS ${accessKeyId}:${check_signature}" \
        -w "%{http_code}" \
        -o /dev/null \
        "${url}" 2>/dev/null)
    
    checkedFilesCount=$((checkedFilesCount + 1))
    
    if [ "$check_response" -eq 200 ]; then
        echo "✅ 文件存在: ${url}"
        return 0
    elif [ "$check_response" -eq 404 ]; then
        echo "❌ 文件不存在: ${url}"
        echo "${url}" >> "$output_file"
        notExistFilesCount=$((notExistFilesCount + 1))
        return 0
    else
        echo "❌ 检查文件存在时出错 (HTTP ${check_response}): ${url}"
        return 1
    fi
}
 
#检索参数指定的待检查的目录
function recursion_dir(){
    curPath=$1
    for pathname in "$curPath"/*
    do
        if [ -d "$pathname" ]
        then
            recursion_dir "$pathname"
        else
            # 只取文件名，去掉前面的路径
            filename=$(basename "$pathname")
            checkFileInOss "${pathname}" "${destDir}/${filename}"
        fi
    done
}
 
#判断检查的是目录还是文件
if [ -d "$sourceFileOrDir" ]
then
    #调用文件夹检查
    recursion_dir "$sourceFileOrDir"
else
    #直接调用检查
    checkFileInOss "$sourceFileOrDir" "$destDir/$sourceFileOrDir"
fi
 
echo "检查完成：总共检查了 ${checkedFilesCount} 个文件，发现 ${notExistFilesCount} 个文件不存在"
echo "不存在的文件列表已保存到 ${output_file}" 